#include <iostream>
#include <unordered_map>
#include <vector>
#include <functional>
#include <memory>
#include <cstdint>
#include <unistd.h>


using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;

class TimerTask{
    private:
        uint64_t _id;           // 定时器任务对象ID
        uint32_t _timeout;      // 定时器任务超时时间
        TaskFunc _task_cb;      // 定时器对象要执行的定时任务
        bool _canceled;         // 定时任务是否被取消 
        ReleaseFunc _release;   // 用于删除TimeWheel中保存的定时器对象信息
    public:
        TimerTask(uint64_t id, uint32_t delay, const TaskFunc& cb)
        :_id(id), _timeout(delay), _task_cb(cb)
        {}
        ~TimerTask() 
        { 
            if (_canceled == false)
            {
                _task_cb(); 
                _release(); 
            }
        }
        void Cancel() { _canceled = true; }
        void SetRelease(const ReleaseFunc& cb) { _release = cb; }
        uint32_t DelayTime() { return _timeout; }
};

class TimerWheel{
    private:
        using PtrTask = std::shared_ptr<TimerTask>;
        using WeakTask = std::weak_ptr<TimerTask>;
        int _tick;                                      // 秒针-走到哪哪里的任务就要被执行
        int _capacity;                                  // 表盘最大数量-也就是最大延迟时间
        std::vector<std::vector<PtrTask>> _wheel;       // 时间轮
        std::unordered_map<uint64_t, WeakTask> _timers; // 使用弱引用，方便刷新/延迟定时任务
    private:
        void RemoveTimer(uint64_t id)
        {
            auto it = _timers.find(id);
            if (it != _timers.end())
            {
                _timers.erase(it);
            }
        }
    public:
        TimerWheel():_tick(0), _capacity(60), _wheel(_capacity) {}

        // 添加定时任务
        void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc& cb)
        {
            PtrTask pt(new TimerTask(id, delay, cb));
            pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));
            int pos = (_tick + delay) % _capacity;
            _wheel[pos].push_back(pt);
            _timers[id] = WeakTask(pt);
        }

        // 刷新/延迟定时任务
        void TimerRefresh(uint64_t id)
        {
            auto it = _timers.find(id);
            if (it == _timers.end())
            {
                return;
            }
            PtrTask pt = it->second.lock();
            int pos = (_tick + pt->DelayTime()) % _capacity;
            _wheel[pos].push_back(pt);
        } 

        void TimerCancel(uint64_t id)
        {
            auto it = _timers.find(id);
            if (it == _timers.end())
                return;
            PtrTask pt = it->second.lock();
            if (pt) pt->Cancel();
        }

        // 这个函数应该每秒钟被执行一次，相当于秒针向后走一步
        void RunTimerTask()
        {
            _tick = (_tick + 1) % _capacity;
            _wheel[_tick].clear(); // 清空该位置数组，就会把数组中所有的定时器对象的shared_ptr释放掉
        }
};

class Test
{
public:
    Test() { std::cout << "构造" << std::endl; } 
    ~Test() { std::cout << "析构" << std::endl; } 
};

void DelTest(Test* ptr)
{
    delete ptr;
}

int main()
{
    TimerWheel tw;
    Test* t = new Test;
    tw.TimerAdd(888, 5, std::bind(DelTest, t));
    for (int i = 0; i < 5; i++)
    {
        sleep(1);
        tw.TimerRefresh(888);
        tw.RunTimerTask();
        std::cout << "刷新了定时任务，需要5s钟后才会执行" << std::endl;
    }
    tw.TimerCancel(888);
    while (1)
    {
        std::cout << "-----------------------------" << std::endl;
        tw.RunTimerTask();
        sleep(1);
    }
    return 0;
}